#include "ct_config.h"
#include "ct_timer.h"

/*****************************************************************************
 * Private Functions
 ****************************************************************************/

/*****************************************************************************
 * Public Functions
 ****************************************************************************/
#ifdef CT_USE_TIMER0
void ct_timer0_run(void) {
    set_TCON_TR0;
}    // start timer0
void ct_timer0_stop(void) {
    clr_TCON_TR0;
}    // stop timer0
void ct_timer0_IntEnable(void) {
    ENABLE_TIMER0_INTERRUPT;
}    // enable timer0 interrupt
void ct_timer0_IntDisable(void) {
    DISABLE_TIMER0_INTERRUPT;
}    // disable timer0 interrupt

void ct_timer0_load(ct_u16 value) {
    TH0 = value >> 8;
    TL0 = value;
}    // load value to timer0
#endif
#ifdef CT_USE_TIMER1
void ct_timer1_run(void) {
    set_TCON_TR1;
}    // start timer1
void ct_timer1_stop(void) {
    clr_TCON_TR1;
}    // stop timer1
void ct_timer1_IntEnable(void) {
    ENABLE_TIMER1_INTERRUPT;
}    // enable timer1 interrupt
void ct_timer1_IntDisable(void) {
    DISABLE_TIMER1_INTERRUPT;
}    // disable timer1 interrupt

void ct_timer1_load(ct_u16 value) {
    TH1 = value >> 8;
    TL1 = value;
}    // load value to timer1
#endif

#ifdef CT_USE_TIMER2
void ct_timer2_run(void) {
    set_T2CON_TR2;
}    // start timer2
void ct_timer2_stop(void) {
    clr_T2CON_TR2;
}    // stop timer2
void ct_timer2_IntEnable(void) {
    ENABLE_TIMER2_INTERRUPT;
}    // enable timer2 interrupt
void ct_timer2_IntDisable(void) {
    DISABLE_TIMER2_INTERRUPT;
}    // disable timer2 interrupt

/* if define TIMER0_FSYS_DIV12, timer = (256-56)*12/246MHz = 100us */
/* if define TIMER0_FSYS, timer = (256-56)/24MHz = 8.33us */
void ct_timer2_load(ct_u16 value) {    // load value to timer2
    SFRS   = 1;
    RCMP2H = value >> 8;
    RCMP2L = value;
    SFRS   = 0;
    TH2    = value >> 8; /* First tmie delay value setting */
    TL2    = value;
}
#endif
/**
 * @brief Timer initialize function
 * @param[in] TIMx Decides the timer. Valid values are:
 *                    - \ref TIMER0
 *                   - \ref TIMER1
 *                - \ref TIMER2
 * @param[in] info Timer initialize structure.
 * @return 0: Success, -1: Invalid timer number, -2: Invalid timer mode, -3: Invalid timer run mode
 * @details This function is used to initialize timer.
 * @note This function is only supported in ML51 series MCU.
 */
char ct_timer_inilize(ct_u8 TIMx, timer_init_t *info) {
    if (TIMx > TIMER2) return -1;
#ifdef CT_USE_TIMER0
    if (TIMx == TIMER0) {
        ct_timer0_stop();
        if (info->intt == TRUE)
            ct_timer0_IntEnable();
        else
            ct_timer0_IntDisable();

        if (info->mode > TIM_TWO_8BIT) return -2;
        switch (info->mode) {
            case TIM_13BIT:
                ENABLE_TIMER0_MODE0;
                break;
            case TIM_16BIT:
                ENABLE_TIMER0_MODE1;
                break;
            case TIM_8BIT_AUTORELOAD:
                ENABLE_TIMER0_MODE2;
                break;
            case TIM_TWO_8BIT:
                ENABLE_TIMER0_MODE3;
                break;
            default:
                break;
        }
        //
        TIMER0_FSYS_DIV12;
        ct_timer0_load(info->value);
        clr_TCON_TF0;
        if (info->run == TRUE) ct_timer0_run();

        return 0;
    }
#endif
#ifdef CT_USE_TIMER1
    if (TIMx == TIMER1) {
        ct_timer1_stop();
        if (info->intt == TRUE)
            ct_timer1_IntEnable();
        else
            ct_timer1_IntDisable();

        if (info->mode > TIM_TWO_8BIT) return -2;
        switch (info->mode) {
            case TIM_13BIT:
                ENABLE_TIMER0_MODE0;
                break;
            case TIM_16BIT:
                ENABLE_TIMER0_MODE1;
                break;
            case TIM_8BIT_AUTORELOAD:
                ENABLE_TIMER0_MODE2;
                break;
            case TIM_TWO_8BIT:
                ENABLE_TIMER0_MODE3;
                break;
            default:
                break;
        }
        //
        TIMER1_FSYS_DIV12;
        ct_timer1_load(info->value);
        clr_TCON_TF1;
        if (info->run == TRUE) ct_timer1_run();

        return 0;
    }
#endif
#ifdef CT_USE_TIMER2
    if (TIMx == TIMER2) {
        ct_timer2_stop();
        if (info->intt == TRUE)
            ct_timer2_IntEnable();
        else
            ct_timer2_IntDisable();

        TIMER2_DIV_4;
        TIMER2_AUTO_RELOAD_DELAY_MODE;
        //
        ct_timer2_load(info->value);
        clr_T2CON_TF2;
        if (info->run == TRUE) ct_timer2_run();

        return 0;
    }
#endif
    return -3;
}
